1. Field of the Invention
The present invention relates to integrated circuit design and, more particularly, to the initialization of the cache portion of a microprocessor design under test.
2. Related Art
Various electronic design automation (EDA) software tools exist for designing microprocessors and other circuitry. Such tools allow circuit designers to create and modify virtual models of the circuit being designed. A circuit designer may, for example, specify a circuit design using a textual description written in a hardware description language (HDL), such as Verilog or VHDL, or by using a graphical user interface to manipulate a graphical representation of the circuit design.
Software tools are also used frequently for testing circuit designs. Circuit testing tools typically simulate the operation of the circuit design; the portion of the testing tool that performs this simulation is therefore called a “simulator.” To test a microprocessor design, for example, the circuit designer typically creates one or more “test cases.” A test case typically specifies a set of initial values for machine resources (such as registers, caches, and main memory) and a set of test microprocessor instructions for the simulator to execute. The test case may also include the outputs that are expected to result from performing the test instructions based on the initial values.
A software program called an “initializer” reads the test case and modifies the initial state of the simulated processor design to reflect the initial state values specified by the test case. Once the processor design is initialized, the simulator simulates the execution of the instructions specified by the test case and verifies that the expected output is produced as a result. A significant advantage of using such simulators for testing is that they may detect errors prior to the costly and time-consuming fabrication of the circuit itself.
Increases in microprocessor speed continue to outpace the speed at which main memory (such as DRAM) may be accessed. As a result, caches have become increasingly important in microprocessor designs. A cache is a high-speed memory, such as SRAM, which stores the contents of main memory locations that have been used frequently and/or recently. It is common for cache latency (access time) to be shorter than main memory latency by a factor of fifty or more. Microprocessor load and store operations attempt to use the cache whenever possible to take advantage of its higher bandwidth. Modern microprocessors typically include at least two levels of cache, referred to as Level 1 (L1) and Level 2 (L2) cache. Cache memory is typically more expensive than main memory due to its high bandwidth. One aspect of microprocessor design therefore involves determining how much of each kind of cache to include in the processor design, based on the tradeoff between speed and cost.
Several kinds of cache architectures are commonly used in microprocessor designs. For example, in a “direct-mapped cache,” main memory is logically subdivided into equal-sized portions, each of which is mapped to a particular cache line. A cache line (also referred to herein as a “cache entry”) is an individual unit of storage in the cache, each of which is typically 256 bits (32 bytes) wide in modern caches. When a read operation requests the value stored in a particular main memory location, the processor maps the memory location's address to the corresponding cache line address and determines whether the cache line contains a valid value for the memory location. If the cache line does not contain a valid value for the memory location, the memory location's value is read from main memory and stored in the cache line for use by subsequent read operations. Store operations map memory addresses to cache lines in the same way.
In a “fully associative cache,” there is no fixed mapping between particular cache lines and particular portions of main memory. Rather, in a fully associative cache, any cache line may store the contents of any memory location. Various techniques have been developed for maintaining and accessing the mapping between memory addresses and cache line addresses in fully associative caches.
In an “N-way associative cache,” the cache is divided into sets of N cache lines each, where N is a number such as 2, 4, or 8. Each set may, for example, correspond to a portion of main memory sharing the same lower bits. Each of the cache lines within a set is referred to as a “way.” Each memory location in main memory typically is mapped to the cache line set associated with the main memory location's lower bits. The contents of a particular memory location may be stored in any of the ways (cache lines) at a particular cache address.
Although portions of main memory are directly mapped to a cache line set (i.e., cache address), an N-way associative cache is associative within each set. Both the direct-mapped cache architecture and the fully associative cache architecture are therefore special cases of the N-way associative cache architecture. For example, a direct-mapped cache is an N-way associative cache in which N is equal to one. Similarly, a fully associative cache is an N-way associative cache in which N is equal to the number of cache lines. One aspect of microprocessor design involves determine which type(s) of cache to use based on various design considerations that are well-known to those of ordinary skill in the art.
As described above, microprocessor designs under test model the resources of a microprocessor, including its cache(s). In an N-way associative cache, each cache line may be uniquely referenced by an address-way pair (A, W), where A is the cache line's address and W is the cache line's way. The cache model in a microprocessor design therefore is typically represented as a two-dimensional data structure. The value stored in the cache model at each index (A, W) represents the value stored in the cache at index (A, W). The cache model therefore represents the state of the cache at a particular point in time.
As described above, circuit design testing tools typically receive as an input a test case which specifies initial conditions for the microprocessor design under test. One portion of the test case typically specifies initial values for the microprocessor cache(s). This “cache portion” of a test case typically includes a list of initialization records, each of which includes: (1) an address A, (2) a way W, and (3) an initial value I to be stored in the cache model at index (A, W). The initializer sequentially reads this list of initialization records and initializes each cache line entry in the microprocessor cache model with the specified initial values.
One or more initialization records in the test case may specify a cache address but not a way. A test case designer may not specify a way in a particular initialization record because, for example, successful execution of the test case requires only that the specified initial value be stored at a particular address but does not require that the specified initial value be stored at a particular way. Cache initialization records which specify an address but not a way present a problem for conventional initializers. Upon encountering an initialization record that specifies a cache address A but not a way, an initializer may, for example, choose a way W using some predetermined method, and store the specified initial value in the cache model at index (A, W). If, however, a subsequent initialization record specifies the same address-way pair (A, W), it will not be possible for the initializer to store the specified initial value in the cache model at index (A, W) because it is already initialized. Failure to store an initial value at the particular address-way pair specified by the test case may cause execution (by the simulator) of the test case to malfunction.
What is needed, therefore, are improved techniques for initializing the cache portion of a microprocessor design under test.